<?php

class pool{

    protected  $server;
    protected  $db_config; //配置信息
    public  function  __construct($config)
    {
        //全局对象
        $this->server=new \swoole\server('0.0.0.0',9501);
        $this->server->set($config['tcp']);
        //注册事件
        $this->server->on('WorkerStart',[$this,'onWorkerStart']);
        $this->server->on('receive',[$this,'onReceive']);
        $this->server->on('task',[$this,'onTask']);
        $this->server->on('finish',[$this,'onFinish']);
        $this->db_config=$config;
        //echo $this->idle_pool->shift();
        $this->server->start(); //全局生命周期
    }

    public  function  onWorkerStart($server,$worker_id){
    }

    public  function  onReceive($server,$fd,$reactor_id,$data){
        $len=unpack('N',$data)[1];
        $body=substr($data,-$len);//去除二进制数据之后,不要包头的数据

        //sql发送过来的时候,发送给连接池 task
        //同步阻塞
//        $result=$server->task($body);
        $result=$server->taskwait($body,10);

        var_dump($result);
//        $server->finish($result);
    }

    /*
     * 自带排队效果
     * 1.没有办法去控制连接池数量,资源非常昂贵
     * 2.多了一次进程间通讯
     * 3.长连接复用连接
     * */
    public  function  onTask($server,$task_id,$worker_id,$data){
        $res=$this->query($data); //执行一条sql
//        var_dump($server->stats());
        sleep(1);

        $server->finish(json_encode($res));
//        return json_encode($res);
//        return $res;
    }

    public  function  onFinish($server,$task_id,$data){
//        var_dump($data);
        echo "task:{$task_id}--处理完成\n";
    }
    protected  function query($sql){

        //执行sql的时候,两次循环,如果执行成功,就跳出循环失败
        $db=$this->db_connect($this->db_config);

        for ($i=0;$i<2;$i++){
            try{
                $res=$db->query($sql);
                echo '111';
                continue;
            }catch (PDOException $e){
                $err_msg=$e->getMessage();
                if(strpos($err_msg,'MySQL server has gone away')!==false){
                    $db=$this->db_connect($this->db_config);
                }
                $res=$db->query($sql);
                break;
            }
        }
        //如果当前是select
        if(preg_match('/^select/i',$sql)){
            $data=$res->fetchAll(PDO::FETCH_ASSOC); //执行查询
        }else{
            $data=$res;
        }
        return $data;
    }

    /**
     * 数据库长连接
     * @param $db_config
     * @return array|PDO
     */
    public  function  db_connect($db_config){
        try{
            $pdo=new PDO($db_config['db']['dsn'],$db_config['db']['user'],$db_config['db']['password'],[PDO::ATTR_PERSISTENT=>true,PDO::ATTR_SERVER_INFO=>true]);
            return $pdo;
        }catch (Exception $e){
            echo $e->getMessage();
            return [];
        }
    }

}

$config['tcp']=[
    'worker_num'=>2,
    'task_worker_num'=>20, //连接池数量
    'open_length_check' => true,
    'package_length_type'=>'N',
    'package_length_offset'=>0, //计算总长度
    'package_body_offset'=>4,//包体位置
];
$config['server']=[
    'max'=>20,
    'min'=>2
];

$config['db']=[
    'dsn'=>'mysql:host=127.0.0.1;dbname=test',
    'user'=>'root',
    'password'=>'Abc123!Abc'
];

new Pool($config);
